﻿#include "mem_Segment.h"
#include "head.h"
#include <string>
#include <bits/stdc++.h>
#include<float.h>
using namespace std;

void SEGEMENT::dispatch_memory_seg(process* PROCESS){
    PPCB *cur=PROCESS->waithead->next;

        while(cur!=PROCESS->waitrear){
            int need=cur->memory;
            SEGETABLE* addr_segetable = new SEGETABLE(need);
            bool flag=true;
            bool flag2;                                              //flag用于标记是否内存遍历完毕也无法为程序段分配
            for(int i=0;i<addr_segetable->num_sege;i++){                   //分配内存
                int j=0;
                while(1){
                    while(j<memory_size&&used_segemap[j])
                    j++;
                    flag2=true;
                    for(int k=0; k < addr_segetable->sege_entry[i][1]; ++k){ //判断后续的 可用帧长度 是否大于 所需长度
                    if(j+k>=memory_size){
                        flag=false;
                        break;
                    }
                    if(used_segemap[j+k] == 1){//后续所需长度里  有 用了的  该段不可用
                        j+=k;//后续从j+k开始
                        flag2=false;                       //flag2用于标记后续所需长度里  有没有用了的  为true表示改段可用
                        break;
                    }
                 }
                 if(flag2)              //flag2为true表示找到了可用的段或内存已遍历完毕
                 break;
                 if(!flag)
                 break;
                }
                if(flag&&flag2){                           //若两个flag均为true表示该段可用 可以分配内存
                    addr_segetable->sege_entry[i][2]=j;    //进程段表记录起始位置
                    for(int k=0; k < addr_segetable->sege_entry[i][1]; ++k)         //已用内存标记为1
                   { used_segemap[j+k] =1;
                    used_frame++;       //更新内存情况
                    Utilization=(float)used_frame/memory_size;}

                }
                else                     //若无法为当前段分配则无需为后续段分配 结束循环
                break;
            }
            if(!flag){                          //若flag为false则表示有段未被分配 将之前分配的回收
                for(int i=0;i<addr_segetable->num_sege;i++){
                    if(addr_segetable->sege_entry[i][2]==0)               //后续的未分配无需回收
                    break;
                    int j=addr_segetable->sege_entry[i][2];
                    for(int k=0;k<addr_segetable->sege_entry[i][1];k++){
                    used_segemap[j+k] = 0;                          //释放内存
                    used_frame--;       //更新内存情况
                    Utilization=(float)used_frame/memory_size;
                    }
                }
            }
            else{                                         //表示该进程所有段都被分配
                cur->segetable=addr_segetable;                                         //为当前pcb分配一个新页表
                PPCB *next=cur;                     //记录等待队列位置
                cur=cur->next;
                PROCESS->Delete_process_byId(next->id,2);
                PROCESS->Insert_ready(next);
                continue;
            }
            cur=cur->next;
        }


}
void SEGEMENT::Delete_seg(process* PROCESS){
    PPCB *cur=PROCESS->finishhead->next;
         while(cur!=PROCESS->finishrear){
            SEGETABLE *addr_segetable=cur->segetable;                          //当前pcb对应的页表
          for(int i=0;i<addr_segetable->num_sege;i++){
                  int j=addr_segetable->sege_entry[i][2];
                  for(int k=0;k<addr_segetable->sege_entry[i][1];k++){
                  used_segemap[j+k] = 0;                          //释放内存
                  used_frame--;       //更新内存情况
                  Utilization=(float)used_frame/memory_size;
                  }
              }
          cur->segetable=NULL;                                 //丢弃当前进程对应的页表
          PPCB *next=cur;                     //记录完成队列位置
          cur=cur->next;
          PROCESS->Delete_process_byId(next->id,5);      //从完成队列中删除进程

      }

}
